#include "app_buffer.h"
#include "log.h"
#include <stdlib.h>
#include <string.h>

// 初始化缓冲区
// 参数：@param 其中一份缓冲区的大小，实际的大小是total_size*2
Buffer *app_buffer_init(int total_size)
{
    // 1.创建大缓冲区
    Buffer *buffer = (Buffer *)malloc(sizeof(Buffer));
    // 2.创建小缓冲区 创建2个缓冲区，每个有单独的内存和空间大小，数据长度
    for (int i = 0; i < 2; i++)
    {
        SubBUffer *sub_buffer = (SubBUffer *)malloc(sizeof(SubBUffer));
        sub_buffer->ptr = malloc(total_size);
        sub_buffer->total_size = total_size;
        sub_buffer->len = 0;
        buffer->sub_buffers[i] = sub_buffer;
    }

    // 指定哪个是读缓冲区，哪个是写缓冲区
    buffer->read_index = 0;  // 读缓冲区
    buffer->write_index = 1; // 写缓冲区
    // 锁初始化

    return buffer;
}

// 向缓冲区写入数据
// 1.获取写缓冲区
// 2.校验长度是否足够写入数据
// 3.写入数据
int app_buffer_write(Buffer *buffer, char *writedata, int writelen)
{
    // 1.获取写缓冲区
    SubBUffer *write_buffer = buffer->sub_buffers[buffer->write_index];
    // 2.校验长度是否足够写入数据
    if (writelen > write_buffer->total_size - write_buffer->len)
    {
        log_error("待写入的数据长度大于缓冲区剩余空间");
        return -1;
    }

    // 3.写入数据
    memcpy(write_buffer->ptr + write_buffer->len, writedata, writelen);
    write_buffer->len += writelen;
    return 0;
}

// 从缓冲区读取数据
/**
 * @param read_buff 读取缓冲区 2.写入的目标空间(已分配空间的) 3.可读取的数据大小
 * @return 返回实际读取的数据大小
 */
int app_buffer_read(Buffer *buffer, char *read_buff, int read_buffer_size)
{
    // 1.获取读缓冲区
    SubBUffer *read_buffer = buffer->sub_buffers[buffer->read_index];
    // 2.获取在当前读缓冲区可读取的长度（从可用空间和当前读缓冲区已有的数据长度取最小值）
    int real_read_size = read_buffer->len < read_buffer_size ? read_buffer->len : read_buffer_size;
    // 3.进行读取数据 1)读取数据到目标空间 2)用后面的数据覆盖前面的数据 3)更新缓冲区数据长度
    if (real_read_size > 0)
    {
        memcpy(read_buff, read_buffer->ptr, real_read_size);
        memmove(read_buffer->ptr, read_buffer->ptr + real_read_size, read_buffer->len - real_read_size);
        read_buffer->len -= real_read_size;
    }

    // 4.只要读缓冲区可读的长度等于0,进行读写缓冲区的交换
    if (read_buffer->len == 0)
    {
        int tmp_index = buffer->read_index;
        buffer->read_index = buffer->write_index;
        buffer->write_index = tmp_index;

        // 获取新的读缓冲区
        read_buffer = buffer->sub_buffers[buffer->read_index];
        // 再次获取可读区域的数据长度
        int remain_read_buff = read_buffer_size - read_buffer->len;
        int swaped_real_read_size = read_buffer->len < remain_read_buff ? read_buffer->len : remain_read_buff;
        if (swaped_real_read_size > 0)
        {
            memcpy(read_buffer + real_read_size, read_buffer, swaped_real_read_size);
            memmove(read_buffer->ptr, read_buffer->ptr + real_read_size, swaped_real_read_size);
            real_read_size += swaped_real_read_size;
        }
    }
    return real_read_size;
}

/**
 * 释放缓冲区
 */
void app_buffer_free(Buffer *buffer)
{
    // 释放所有子缓冲区的数据空间
    free(buffer->sub_buffers[0]->ptr);
    free(buffer->sub_buffers[1]->ptr);
    // 释放所有子缓冲区结构体空间
    free(buffer->sub_buffers[0]);
    free(buffer->sub_buffers[1]);

    // 释放大缓冲区的结构体空间
    free(buffer);
}